package edu.stanford.bmir.protege.web.client.ui.ontology.stkos.enricher.recommended;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.UrlParam;
import com.gwtext.client.data.ArrayReader;
import com.gwtext.client.data.FieldDef;
import com.gwtext.client.data.ObjectFieldDef;
import com.gwtext.client.data.Record;
import com.gwtext.client.data.RecordDef;
import com.gwtext.client.data.Store;
import com.gwtext.client.data.StringFieldDef;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.MessageBox;
import com.gwtext.client.widgets.Toolbar;
import com.gwtext.client.widgets.ToolbarButton;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.grid.BaseColumnConfig;
import com.gwtext.client.widgets.grid.CheckboxColumnConfig;
import com.gwtext.client.widgets.grid.CheckboxSelectionModel;
import com.gwtext.client.widgets.grid.ColumnConfig;
import com.gwtext.client.widgets.grid.ColumnModel;
import com.gwtext.client.widgets.grid.GridPanel;
import com.gwtext.client.widgets.grid.RowNumberingColumnConfig;
import com.gwtext.client.widgets.tree.TreeNode;

import edu.stanford.bmir.protege.web.client.project.Project;
import edu.stanford.bmir.protege.web.client.rpc.data.EntityData;
import edu.stanford.bmir.protege.web.client.rpc.data.PropertyEntityData;
import edu.stanford.bmir.protege.web.client.rpc.data.PropertyType;
import edu.stanford.bmir.protege.web.client.rpc.data.SubclassEntityData;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.StkosUtilServiceManager;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.UtilEntityType;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.CandidateEntity;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.EnrichmentOptions;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.OriginEntity;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.actions.CreateCandidateClassesAction;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.enricher.actions.CreateCandidateClassesResult;
import edu.stanford.bmir.protege.web.client.ui.ontology.stkos.common.StkosPanelType;
import edu.stanford.bmir.protege.web.client.ui.portlet.AbstractOWLEntityPortlet;
import edu.stanford.bmir.protege.web.client.ui.util.GWTProxy;
import edu.stanford.bmir.protege.web.shared.DataFactory;
import edu.stanford.bmir.protege.web.shared.event.ClassFrameChangedEvent;
import edu.stanford.bmir.protege.web.shared.event.DatatypeFrameChangedEvent;
import edu.stanford.bmir.protege.web.shared.event.EntityFrameChangedEvent;
import edu.stanford.bmir.protege.web.shared.event.EventBusManager;
import edu.stanford.bmir.protege.web.shared.event.ObjectPropertyFrameChangedEvent;
import edu.stanford.bmir.protege.web.shared.hierarchy.ClassHierarchyParentAddedEvent;
import edu.stanford.bmir.protege.web.shared.hierarchy.DataPropertyHierarchyParentAddedEvent;
import edu.stanford.bmir.protege.web.shared.hierarchy.HierarchyId;
import edu.stanford.bmir.protege.web.shared.hierarchy.ObjectPropertyHierarchyParentAddedEvent;

public class CopyOfStkosEnricherRecommendedPortlet extends AbstractOWLEntityPortlet {

	private static final String OBJECTFIELDDEF = "entity";

	private GridPanel gridPanel;

	private StkosEnricherRecommendedProxy proxy;

	private TreeNode selectedTreeNode;

	private UtilEntityType entityType;

	public static final ArrayReader reader = new ArrayReader(new RecordDef(
			new FieldDef[] { new ObjectFieldDef(OBJECTFIELDDEF),
					new StringFieldDef("browserText"),
					new StringFieldDef("sourceLabel") }));
	
	public static final ArrayReader reader2 = new ArrayReader(new RecordDef(
			new FieldDef[] { new ObjectFieldDef(OBJECTFIELDDEF),
					new StringFieldDef("rndRelation"),
					new StringFieldDef("rndItem"),
					new StringFieldDef("rndsource") }));

	public CopyOfStkosEnricherRecommendedPortlet(Project project) {
		super(project);
	}

	@Override
	public Collection<EntityData> getSelection() {
		return null;
	}

	@Override
	public void onRefresh() {
	}

	@Override
	public void reload() {
	}

	@Override
	public void initialize() {
		setTitle("推荐条目");
		setHeight(720);

		initView();
	}

	private void initView() {
		proxy = new StkosEnricherRecommendedProxy();

		gridPanel = new GridPanel();

		CheckboxSelectionModel checkboxSelectionModel = new CheckboxSelectionModel();
		gridPanel.setSelectionModel(checkboxSelectionModel);

		CheckboxColumnConfig checkCol = new CheckboxColumnConfig(
				checkboxSelectionModel);

		RowNumberingColumnConfig indexCol = new RowNumberingColumnConfig();

		ColumnConfig recommendedCol = new ColumnConfig();
		recommendedCol.setHeader("推荐条目");
		recommendedCol.setDataIndex("browserText");
		recommendedCol.setSortable(true);

		ColumnConfig sourceCol = new ColumnConfig();
		sourceCol.setHeader("来源");
		sourceCol.setDataIndex("sourceLabel");
		sourceCol.setSortable(true);

		BaseColumnConfig[] columns = new BaseColumnConfig[] { checkCol,
				indexCol, recommendedCol, sourceCol };

		ColumnModel columnModel = new ColumnModel(columns);
		gridPanel.setColumnModel(columnModel);

		Store store = new Store(proxy, reader);

		ToolbarButton tbtn = new ToolbarButton("添加为子类");
		tbtn.setDisabled(!hasWritePermission());
		tbtn.addListener(new ButtonListenerAdapter() {
			@Override
			public void onClick(final Button button, final EventObject e) {
				addAsChild();
			}
		});

		Toolbar toolbar = new Toolbar();
		toolbar.addButton(tbtn);

		gridPanel.setTopToolbar(toolbar);

		gridPanel.setStore(store);

		gridPanel.setStripeRows(true);
		gridPanel.setAutoExpandColumn(3);
		gridPanel.setBorder(false);

		add(gridPanel);
	}

	protected void addAsChild() {
		Record[] records = gridPanel.getSelectionModel().getSelections();
		if (records == null || records.length == 0) {
			MessageBox.alert("提示", "至少选择一项进行操作!");
			return;
		}
		if (selectedTreeNode == null
				|| selectedTreeNode.getUserObject() == null) {
			MessageBox.alert("提示", "所需必要信息不完整、操作失败!");
			return;
		}
		EntityData entityData = (EntityData) selectedTreeNode.getUserObject();
		String parentName = entityData.getName();
		ArrayList<CandidateEntity> candidateEntities = new ArrayList<CandidateEntity>();
		for (Record record : records) {
			if (record.getAsObject(OBJECTFIELDDEF) != null) {
				CandidateEntity candidateEntity2 = (CandidateEntity) record
						.getAsObject(OBJECTFIELDDEF);

				CandidateEntity candidateEntity = new CandidateEntity();
				candidateEntity.setBrowserText(candidateEntity2
						.getBrowserText());
				candidateEntity.setSourceLabel(candidateEntity2
						.getSourceLabel());
				candidateEntity.setEntityType(entityType);
				candidateEntities.add(candidateEntity);
			}
		}

		CreateCandidateClassesAction action = new CreateCandidateClassesAction(
				parentName, candidateEntities);

		AsyncCallback<CreateCandidateClassesResult> callback = new AsyncCallback<CreateCandidateClassesResult>() {

			@Override
			public void onFailure(Throwable caught) {
				GWT.log("Add as child operation failure.", caught);
				MessageBox.alert("提示", "添加子类操作失败!");
			}

			@Override
			public void onSuccess(final CreateCandidateClassesResult result) {
				EntityData entityData = (EntityData) selectedTreeNode.getUserObject();
				String parent = entityData.getName();
				String child = null;
				if(result!=null&&result.getSubClassEntityDataList()!=null&&result.getSubClassEntityDataList().size()>0){
					for(SubclassEntityData sed:result.getSubClassEntityDataList()){
						if(sed!=null&&sed.getName()!=null){
							child = sed.getName();
							break;
						}
					}
				}
				refreshSelectedTreeNode(parent,child);
			}
		};
		StkosUtilServiceManager.getInstance().createCandidateClasses(
				this.getProject().getProjectId().getId(), action, callback);
	}
	
	protected void refreshSelectedTreeNode(String name,String child) {
		if (getProject() == null || getProject().getProjectId() == null
				|| name == null) {
			return;
		}
		EventBusManager manager = EventBusManager.getManager();

		List<EntityFrameChangedEvent> events = new ArrayList<EntityFrameChangedEvent>();
		if (UtilEntityType.CLASS.equals(entityType)) {
			ClassFrameChangedEvent event = new ClassFrameChangedEvent(
					DataFactory.getOWLClass(name), getProject().getProjectId());
			events.add(event);
			
			if(child!=null){
				ClassHierarchyParentAddedEvent chpae = new ClassHierarchyParentAddedEvent(getProjectId(),DataFactory.getOWLClass(child),DataFactory.getOWLClass(name),HierarchyId.CLASS_HIERARCHY);
				manager.postEvent(chpae);
			}
		}
		if (UtilEntityType.DATA_PROPERTY.equals(entityType)) {
			DatatypeFrameChangedEvent event2 = new DatatypeFrameChangedEvent(
					DataFactory.getOWLDatatype(name),
					getProject().getProjectId());
			events.add(event2);
			
			if(child!=null){
				DataPropertyHierarchyParentAddedEvent dhpae = new DataPropertyHierarchyParentAddedEvent(getProjectId(),DataFactory.getOWLDataProperty(child),DataFactory.getOWLDataProperty(name),HierarchyId.DATA_PROPERTY_HIERARCHY);
				manager.postEvent(dhpae);
			}
		}
		if (UtilEntityType.OBJECT_PROPERTY.equals(entityType)) {
			ObjectPropertyFrameChangedEvent event3 = new ObjectPropertyFrameChangedEvent(
					DataFactory.getOWLObjectProperty(name),
					getProject().getProjectId());
			events.add(event3);
			
			if(child!=null){
				ObjectPropertyHierarchyParentAddedEvent ohpae = new ObjectPropertyHierarchyParentAddedEvent(getProjectId(),DataFactory.getOWLObjectProperty(child),DataFactory.getOWLObjectProperty(name),HierarchyId.OBJECT_PROPERTY_HIERARCHY);
				manager.postEvent(ohpae);
			}
		}
		
		if (events != null && events.size() > 0) {
			for (EntityFrameChangedEvent event : events) {
				if (event != null) {
					manager.postEvent(event);
				}
			}
		}
	}

	public void setSelectedTreeNode(StkosPanelType type,
			EnrichmentOptions options, TreeNode selectedTreeNode) {
		gridPanel.getStore().removeAll();
		if (type == null) {
			GWT.log("type is null.");
			return;
		}
		if (options == null) {
			GWT.log("options is null.");
			return;
		}
		if (selectedTreeNode == null) {
			GWT.log("selectedTreeNode is null.");
			return;
		}
		this.selectedTreeNode = selectedTreeNode;
		String projectName = getProjectId().getId();
		EntityData entityData = (EntityData) selectedTreeNode.getUserObject();

		OriginEntity originEntity = new OriginEntity();
		if (StkosPanelType.CLASS_TREE.equals(type)) {
			originEntity.setEntityType(UtilEntityType.CLASS);
		} else if (StkosPanelType.PROPERTY_TREE.equals(type)) {
			if (entityData == null) {
			} else {
				PropertyEntityData ped = (PropertyEntityData) entityData;
				if (PropertyType.DATATYPE.equals(ped.getPropertyType())) {
					originEntity.setEntityType(UtilEntityType.DATA_PROPERTY);
				} else if (PropertyType.OBJECT.equals(ped.getPropertyType())) {
					originEntity.setEntityType(UtilEntityType.OBJECT_PROPERTY);
				} else if (PropertyType.ANNOTATION
						.equals(ped.getPropertyType())) {
				} else {
				}
			}
		} else if (StkosPanelType.INDIVIDUAL_TREE.equals(type)) {
		} else {
		}
		this.entityType = originEntity.getEntityType();
		originEntity.setBrowserText(entityData.getBrowserText());
		AsyncCallback<List<CandidateEntity>> callback = new AsyncCallback<List<CandidateEntity>>() {

			@Override
			public void onFailure(Throwable caught) {
				GWT.log("获取推荐条目失败.", caught);
				MessageBox.alert("提示", "获取推荐条目失败!");
			}

			@Override
			public void onSuccess(List<CandidateEntity> result) {
				proxy.setResults(result);
				gridPanel.getStore().load();
			}
		};

		StkosUtilServiceManager.getInstance().fetchCandidateEntities(
				projectName, originEntity, options, callback);
	}

	protected class StkosEnricherRecommendedProxy extends GWTProxy {

		private List<CandidateEntity> results;

		@Override
		public void load(int start, int limit, String sort, String dir,
				final JavaScriptObject o, UrlParam[] baseParams) {
			if (results == null || results.size() == 0) {
				loadResponse(o, false, 0, (JavaScriptObject) null);
			} else {
				loadResponse(o, true, results.size(), getRecords(results));
			}
			unmark();
		}

		private Object[][] getRecords(List<CandidateEntity> result) {
			Object[][] resultAsObjects = new Object[result.size()][3];

			int i = 0;
			for (CandidateEntity ed : result) {
				Object[] obj = new Object[] { ed, ed.getBrowserText(),
						ed.getSourceLabel() };
				resultAsObjects[i++] = obj;
			}
			return resultAsObjects;
		}

		public void setResults(List<CandidateEntity> results) {
			this.results = results;
		}
	}

	public void mark() {
		if (getBody() != null) {
			getBody().mask("Load...", true);
		}
	}

	public void unmark() {
		if (getBody() != null) {
			getBody().unmask();
		}
	}
}
